package com.atguigu.gmall.activity.listener;

import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.activity.util.DateUtil;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.UserRecode;
import com.atguigu.gmall.mq.mqconst.MqTaskConst;
import com.atguigu.gmall.mq.mqconst.MqseckillConst;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class ActivityListener {

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private SeckillGoodsService seckillGoodsService;

    @Autowired
    private RedisTemplate redisTemplate;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqTaskConst.QUEUE_TASK, durable = "true", autoDelete = "false"),
            exchange = @Exchange(value = MqTaskConst.EXCHANGE_TASK, durable = "true", autoDelete = "false"),
            key = {MqTaskConst.ROUTING_KEY_TASK}
    ))
    public void messageTask(Message message, Channel channel) throws IOException {
        try {
            QueryWrapper<SeckillGoods> seckillGoodsQueryWrapper = new QueryWrapper<>();
            seckillGoodsQueryWrapper.eq("status", 1);
            seckillGoodsQueryWrapper.eq("date_format(start_time,'%Y-%m-%d')", DateUtil.formatDate(new Date()));
            seckillGoodsQueryWrapper.gt("stock_count", 0);

            List<SeckillGoods> seckillGoods = seckillGoodsMapper.selectList(seckillGoodsQueryWrapper);
            if (CollectionUtils.isEmpty(seckillGoods)) {
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                return;
            }


            Map<String, SeckillGoods> seckillGoodsMap = seckillGoods.stream()
                    .collect(Collectors.toMap(seckillGoodsKey -> {
                        return seckillGoodsKey.getSkuId().toString();
                    }, seckillGoodsValues -> {
                        return seckillGoodsValues;
                    }));

            HashOperations hashOperations = redisTemplate.opsForHash();
            String seckillGoodsMapKey = RedisConst.SECKILL_GOODS;
            hashOperations.putAll(seckillGoodsMapKey, seckillGoodsMap);


            for (SeckillGoods seckillGood : seckillGoods) {
                Integer stockCount = seckillGood.getStockCount();
                if (stockCount == 0) {
                    continue;
                }
                Long skuId = seckillGood.getSkuId();

                HashOperations hashOperations2 = redisTemplate.opsForHash();
                hashOperations2.put(RedisConst.SECKILL_SALE_PRODUCTED, skuId.toString(), seckillGood.getStockCount());

                redisTemplate.convertAndSend("seckillpush", skuId + ":1");
            }
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            Boolean redelivered = message.getMessageProperties().getRedelivered();
            if (redelivered) {
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            } else {
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            }
        }

    }


    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqseckillConst.QUEUE_SECKILL, durable = "true", autoDelete = "false"),
            exchange = @Exchange(value = MqseckillConst.EXCHANGE_SECKILL, durable = "true", autoDelete = "false"),
            key = {MqseckillConst.ROUTING_KEY_SECKILL}
    ))
    public void messageSeckillGods(Message message, Channel channel, UserRecode userRecode) throws IOException {
        try {
            seckillGoodsService.preSeckillGoodsOrder(userRecode);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            Boolean redelivered = message.getMessageProperties().getRedelivered();
            if (redelivered) {
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            }else{
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            }
        }
    }
}
